package com.baozun.util;

import java.io.File;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.apache.commons.io.FileUtils;

/**
 * 从数据库中读取表信息，生成注解基类
 * 
 * @Title:基类工具
 * @Company:宝尊电子商务有限公司
 * @Author:万世极缘
 * @Since:2014-12-28
 * @Copyright:Copyright (c) 2014
 * @ModifyDate:2014-12-28
 * @Version:1.1.0
 */
public class GenEntityUtil {

    private String[] tableColumnNames;
    private String[] colnames; // 列名数组
    private String[] colTypes; // 列名类型数组
    private int[] colSizes;
    private String key;
    private boolean f_util = false; // 是否需要导入包java.util.*
    private boolean f_sql = false; // 是否需要导入包java.sql.*
    private boolean f_text = false;// 是否需要导入java.text.*包

    /**
     * 
     * @param resourcePath 资源路径
     * @param packagePath 包路径
     * @param tableName 表名
     */
    public GenEntityUtil(String resourcePath, String packagePath, String tableName) {
        initColumn(packagePath, tableName);
        initKey(tableName);
        createFile(resourcePath, packagePath, tableName);
    }

    public void initColumn(String packagePath, String tableName) {
        Connection conn = DatabaseUtils.openConnection(); // 得到数据库连接
        PreparedStatement pstmt = null;
        String strsql = "select * from " + tableName;
        try {
            pstmt = conn.prepareStatement(strsql);
            ResultSetMetaData rsmd = pstmt.getMetaData();
            int size = rsmd.getColumnCount(); // 共有多少列
            colnames = new String[size];
            colTypes = new String[size];
            colSizes = new int[size];
            tableColumnNames = new String[size];
            for (int i = 0; i < rsmd.getColumnCount(); i++) {
                colnames[i] = this.initcap(rsmd.getColumnName(i + 1));
                tableColumnNames[i] = rsmd.getColumnName(i + 1);
                colTypes[i] = rsmd.getColumnTypeName(i + 1);
                if (colTypes[i].equalsIgnoreCase("datetime")) {
                    f_util = true;
                    f_text = true;
                }
                if (colTypes[i].equalsIgnoreCase("image") || colTypes[i].equalsIgnoreCase("text") || colTypes[i].equalsIgnoreCase("blob") || colTypes[i].equalsIgnoreCase("clob")) {
                    f_sql = true;
                }
                if (colTypes[i].equalsIgnoreCase("decimal") || colTypes[i].equalsIgnoreCase("integer")) {
                    f_text = true;
                }
                colSizes[i] = rsmd.getColumnDisplaySize(i + 1);
            }

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DatabaseUtils.closeDatabase(conn, pstmt, null);
        }
    }

    private void initKey(String tableName) {
        Connection conn = DatabaseUtils.openConnection(); // 得到数据库连接
        ResultSet rs = null;
        DatabaseMetaData dmd = null;
        try {
            dmd = conn.getMetaData();
            rs = dmd.getPrimaryKeys(null, null, tableName);
            System.out.println(rs);
            rs.next();
            key = (String) rs.getObject(4);
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DatabaseUtils.closeDatabase(conn, null, rs);
        }
    }

    private void createFile(String resourcePath, String packagePath, String tableName) {
        try {
            String content = parse(colnames, colTypes, colSizes, packagePath, tableName);
            String path = System.getProperty("user.dir") + "/" + resourcePath + "/" + packagePath.replaceAll("\\.", "/");
            File file = new File(path);
            if (!file.exists()) {
                file.mkdirs();
            }
            String resPath = path + "/" + getResource(initcap(tableName)) + ".java";
            System.out.println("resPath=" + resPath);
            FileUtils.writeStringToFile(new File(resPath), content);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 解析处理(生成实体类主体代码)
     */
    private String parse(String[] colNames, String[] colTypes, int[] colSizes, String packagePath, String tableName) {
        Date date = new Date();
        SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd");
        SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy");
        StringBuffer sb = new StringBuffer();
        sb.append("package " + packagePath + ";\r\n\r\n");
        if (f_util) {
            sb.append("import java.util.*;\r\n");
        }
        if (f_sql) {
            sb.append("import java.sql.*;\r\n\r\n\r\n");
        }
        if (f_text) {
            sb.append("import java.text.*;\r\n\r\n\r\n");
        }
        sb.append("import javax.persistence.*;\r\n");
        sb.append("import org.hibernate.annotations.GenericGenerator;\r\n");
        sb.append("\n");
        sb.append("/**\n");
        sb.append(" *\n");
        sb.append(" * @Title:\n");
        sb.append(" * @Company:宝尊电子商务有限公司\n");
        sb.append(" * @Author:万世极缘\n");
        sb.append(" * @Since:").append(sdf1.format(date)).append("\n");
        sb.append(" * @Copyright:Copyright (c) ").append(sdf2.format(date)).append("\n");
        sb.append(" * @ModifyDate:").append(sdf1.format(date)).append("\n");
        sb.append(" * @Version:1.1.0\n");
        sb.append(" */\n");
        sb.append("@Entity\n");
        sb.append("@Table(name=\"" + tableName + "\")\n");
        sb.append("public class " + getResource(initcap(tableName)) + " {\r\n\r\n");
        sb.append("\n");
        processAllParam(sb);
        sb.append("\n");
        processAllAttrs(sb);
        sb.append("\r\n");
        processAllMethod(sb);
        sb.append("}\r\n");
        System.out.println(sb.toString());
        return sb.toString();

    }

    /**
     * 生成所有字段常量
     * 
     * @param sb
     */
    private void processAllParam(StringBuffer sb) {
        for (int i = 0; i < colnames.length; i++) {
            sb.append("\t/**").append(colnames[i]).append("******************/");
            sb.append("\n");
            sb.append("\tpublic static final String ");
            sb.append(tableColumnNames[i]);
            sb.append(" = ");
            sb.append("\"").append(colnames[i]).append("\";");
            sb.append("\n");
        }
    }

    /**
     * 生成所有的方法
     * 
     * @param sb
     */
    private void processAllMethod(StringBuffer sb) {
        for (int i = 0; i < colnames.length; i++) {
            sb.append("\tpublic void set" + getResource(colnames[i]) + "(" + sqlType2JavaType(colTypes[i]) + " " + colnames[i] + "){\r\n");
            sb.append("\t\tthis." + colnames[i] + "=" + colnames[i] + ";\r\n");
            sb.append("\t}\r\n\r\n");

            sb.append("\tpublic " + sqlType2JavaType(colTypes[i]) + " get" + getResource(colnames[i]) + "(){\r\n");
            sb.append("\t\treturn " + colnames[i] + ";\r\n");
            sb.append("\t}\r\n\r\n");

            sb.append("\t/**\n");
            sb.append("\t* 输出显示\n");
            sb.append("\t*/\n");
            if (colTypes[i].equalsIgnoreCase("date") || colTypes[i].equalsIgnoreCase("datetime")) {
                sb.append("\tpublic String " + colnames[i] + "2Html(String pattern){\r\n");
                sb.append("\t\treturn ").append(colnames[i]).append(" == null ? \"\":new SimpleDateFormat(pattern).format(").append(colnames[i]).append(");\r\n");
            } else if (colTypes[i].equalsIgnoreCase("varchar") || colTypes[i].equalsIgnoreCase("char")) {
                sb.append("\tpublic String " + colnames[i] + "2Html(){\r\n");
                sb.append("\t\treturn ").append(colnames[i]).append(" == null ? \"\":").append(colnames[i]).append(";\r\n");
            } else {
                sb.append("\tpublic String " + colnames[i] + "2Html(String pattern){\r\n");
                sb.append("\t\treturn ").append(colnames[i]).append(" == null ? \"\":new DecimalFormat(pattern).format(").append(colnames[i]).append(");\r\n");
            }
            sb.append("\t}\r\n\r\n");
        }
    }

    private String getResource(String colname) {
        StringBuffer result = new StringBuffer();
        result.append((colname.substring(0, 1)).toUpperCase()).append(colname.substring(1));
        return result.toString();
    }

    /**
     * 解析输出属性
     * 
     * @return
     */
    private void processAllAttrs(StringBuffer sb) {
        for (int i = 0; i < colnames.length; i++) {
            if (tableColumnNames[i].equals(key)) {
                sb.append("\t@Id");
                sb.append("\n");
                if (sqlType2JavaType(colTypes[i]).equals("bool") || sqlType2JavaType(colTypes[i]).equals("byte") || sqlType2JavaType(colTypes[i]).equals("short") || sqlType2JavaType(colTypes[i]).equals("int")
                        || sqlType2JavaType(colTypes[i]).equals("float") || sqlType2JavaType(colTypes[i]).equals("double")) {
                    sb.append("\t@GeneratedValue(strategy=\"GenerationType.IDENTITY\")");
                } else {
                    sb.append("\t@GeneratedValue(generator=\"system-uuid\")");
                    sb.append("\n");
                    sb.append("\t@GenericGenerator(name = \"system-uuid\",strategy=\"uuid\")");
                }
                sb.append("\n");
            }
            sb.append("\t@Column(name=\"" + tableColumnNames[i] + "\")\n");
            sb.append("\tprivate " + sqlType2JavaType(colTypes[i]) + " " + colnames[i] + ";\r\n");
        }
    }

    /**
     * 把输入字符串的首字母改成大写
     * 
     * @param str
     * @return
     */
    private String initcap(String str) {
        // 全部小写
        str = str.toLowerCase();
        char[] chArray = str.toCharArray();
        StringBuffer sb = new StringBuffer("");
        for (int i = 0; i < chArray.length; i++) {
            char ch = chArray[i];
            if ('_' == ch) {
                sb.append((chArray[i + 1] + "").toUpperCase());
                i++;
            } else {
                sb.append(ch);
            }
        }
        return sb.toString();
    }

    private String sqlType2JavaType(String sqlType) {
        if (sqlType.equalsIgnoreCase("bit")) {
            return "bool";
        } else if (sqlType.equalsIgnoreCase("tinyint")) {
            return "Byte";
        } else if (sqlType.equalsIgnoreCase("smallint")) {
            return "Short";
        } else if (sqlType.equalsIgnoreCase("int") || sqlType.equalsIgnoreCase("integer")) {
            return "Integer";
        } else if (sqlType.equalsIgnoreCase("bigint")) {
            return "Long";
        } else if (sqlType.equalsIgnoreCase("float")) {
            return "Float";
        } else if (sqlType.equalsIgnoreCase("decimal") || sqlType.equalsIgnoreCase("numeric") || sqlType.equalsIgnoreCase("real")) {
            return "Double";
        } else if (sqlType.equalsIgnoreCase("money") || sqlType.equalsIgnoreCase("smallmoney")) {
            return "Double";
        } else if (sqlType.equalsIgnoreCase("varchar") || sqlType.equalsIgnoreCase("char") || sqlType.equalsIgnoreCase("nvarchar") || sqlType.equalsIgnoreCase("nchar")) {
            return "String";
        } else if (sqlType.equalsIgnoreCase("datetime") || sqlType.equalsIgnoreCase("date")) {
            return "Date";
        }

        else if (sqlType.equalsIgnoreCase("image") || sqlType.equalsIgnoreCase("blob")) {
            return "Blob";
        } else if (sqlType.equalsIgnoreCase("text") || sqlType.equalsIgnoreCase("clob") || sqlType.equalsIgnoreCase("longtext")){
            return "Clob";
        }
        return null;
    }

    public static void main(String[] args) {
        String resourcePath = "src.main.java";
        String packagePath = "com.baozun.model";
//        new GenEntityUtil(resourcePath, packagePath, "t_user");
//         new GenEntityUtil(resourcePath,packagePath, "t_contact");
//         new GenEntityUtil(resourcePath,packagePath, "t_workrecord");
//        new GenEntityUtil(resourcePath, packagePath, "t_chat");
//        new GenEntityUtil(resourcePath, packagePath, "t_user_info");
        new GenEntityUtil(resourcePath, packagePath, "t_appendix");
        new GenEntityUtil(resourcePath, packagePath, "t_photo");
//        new GenEntityUtil(resourcePath, packagePath, "t_find_mail");
    }

}
